#include "chatDatabase.h"

ChatDatabase *ChatDatabase::instance = new ChatDatabase();
// 需要在类外部定义静态成员变量
unordered_map<string, int> ChatDatabase::onlineUser;
ChatDatabase::ChatDatabase()
{
    mysql = nullptr;
}

ChatDatabase::~ChatDatabase()
{
}

void ChatDatabase::make_uid(string &uid)
{

    srand(time(0));

    char tmp = 0;
    for (int i = 0; i < 6; ++i)
    {
        int mode = random() % 2;
        switch (mode)
        {
        case 0:
            tmp = random() % 10;
            tmp += '0';
            break;
        case 1:
            tmp = random() % 26;
            tmp += 'A';
            break;
        default:
            tmp = random() % 26;
            tmp += 'a';
            break;
        }
        uid += tmp;
    }
}

void ChatDatabase::my_database_connect(const char *db_name)
{

    this->mysql = mysql_init(NULL);

    this->mysql = mysql_real_connect(this->mysql, "192.168.1.103", "fyq", "123456",
                                     db_name, 0, NULL, 0);
    if (NULL == this->mysql)
    {
        cout << "mysql_real_connect error" << endl;
    }
}

MYSQL_RES *ChatDatabase::get_MYSQL_RES(MYSQL *mysql, const char *sqlscript)
{

    if (mysql_query(mysql, sqlscript) != 0)
    {
        cout << "mysql_query error" << mysql_error(mysql) << endl;
        return nullptr;
    }
    cout << "sql1" << endl;
    MYSQL_RES *res = mysql_store_result(mysql);
    if (NULL == res)
    {
        cout << "mysql_store_result error" << endl;
        return nullptr;
    }
    else
    {
        return res;
    }
    cout << "sql2" << endl;
}

int ChatDatabase::my_database_get_data(vector<string> &array, const char *sqlscript)
{

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, sqlscript);
    if (NULL == res)
    {
        return -1;
    }

    int column = mysql_num_fields(res); // 获取列数
    int rn = mysql_num_rows(res);       // 获取行数
    // cout << "column: " << column << endl;

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res))) // 从结果集中获取下一行的函数
    {

        string tmp;
        if (column == 1)
        {
            tmp += row[0]; // 只有一列数据，push进vector里，vector的 索引 是 行
            array.push_back(tmp);
        }
        else
        {
            if (rn == 1)
            { // 只有一行数据，push进vector里，vector的 索引 是 列
                for (int i = 0; i < column; ++i)
                {
                    tmp += row[i];
                    array.push_back(tmp);
                    tmp.clear();
                }
            }
            else
            { // 多行多列，vector的 索引 是 行，每列用 '|' 隔开
                for (int i = 0; i < column; ++i)
                {
                    tmp += row[i];
                    tmp += '|';
                }
                array.push_back(tmp);
            }
        }
    }

    if (rn == 1 || column == 1)
        return 1;
    else if (rn == 0)
        return 0;
    else
        return 2;
}

bool ChatDatabase::my_database_user_exist(const string &user, string *retuid)
{

    ostringstream buffer;

    buffer << "select uid from user where username = '" << user << "';";
    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    if (nullptr == res)
    {

        return -1;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    if (NULL == row)
    {

        return false;
    }
    else if (retuid != nullptr)
    {

        *retuid = row[0];
        return true;
    }
}

int ChatDatabase::my_database_user_register(string name, string password)
{

    // 随机生成不重复的用户uid
    string uid;
    make_uid(uid); // 随机产生6位数字

    ostringstream buffer;
    buffer << "select uid from user where uid = '" << uid << "';";
    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (res == NULL)
    {
        cout << "mysql_query error(uid)" << mysql_error(this->mysql) << endl;
        return -1;
    }

    while (mysql_num_rows(res) != 0)
    {
        // 有重复就清除重新生成
        uid.clear();
        make_uid(uid);

        buffer.str("");
        buffer << "select uid from user where uid = '" << uid << "';";
        string s = buffer.str();

        res = get_MYSQL_RES(this->mysql, s.c_str());
    }

    // 注册用户数据
    buffer.str("");
    statement.clear();
    buffer << "insert into user(username,password,uid) "
           << "values ('" << name << "','" << password << "','" << uid << "');";
    statement = buffer.str();

    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        // cout << "mysql_query error" << endl;
        std::cerr << "mysql_query error: " << mysql_error(this->mysql) << std::endl;
        return -1;
    }

    return 0;
}

int ChatDatabase::my_database_user_confirm(string name, string password)
{

    std::ostringstream buffer;
    buffer << "select uid, username, password from user where username = '" << name << "' AND password = '" << password << "';";

    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    if (NULL == res)
    {
        // return string("");
        return 0;
    }

    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        // return string("none");

        return 0;
    }
    if (password == row[2])
    {

        return 1;
    }
    else
    {
        return 0;
    }
}

void ChatDatabase::my_database_get_friend_list(const string &uid, vector<UserInformation> &array)
{
    ostringstream buf;
    buf << "select friendid from friends where userid = '" << uid << "';";
    string statement = buf.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (res == nullptr)
    {
        return;
    }

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {
        if (row[0] != nullptr)
        {
            UserInformation userInformation;
            my_database_get_user_info(row[0], &userInformation);
            // cout << row[0] << endl;
            array.push_back(userInformation);
        }

        // array.push_back(row[0]);
    }
}

void ChatDatabase::my_database_get_user_info(char *uid, UserInformation *userInformation)
{
    ostringstream buf;
    buf << "select userid, sex, age, birthday, name, headPortrait from userinformation where userid = '" << uid << "';";
    string statement = buf.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        return;
    }
    userInformation->userid = row[0] ? row[0] : "";
    userInformation->sex = row[1] ? row[1] : "";
    userInformation->age = row[2] ? row[2] : "";
    userInformation->birthday = row[3] ? row[3] : "";
    userInformation->name = row[4] ? row[4] : "";
    userInformation->headPortrait = row[5] ? row[5] : "";
}

string ChatDatabase::my_database_user_username(const string &name)
{
    ostringstream buf;
    buf << "select userid from userinformation where name = '" << name << "';";
    string statement = buf.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        return "";
    }
    else
    {
        ostringstream buf ;
        buf << "select username from user where uid = '" << row[0] << "';";
        string statement = buf.str();
        MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
        MYSQL_ROW row = mysql_fetch_row(res);
        if (res != nullptr)
        {
            return row[0];
        }
        else
        {
            return "";
        }
    }
}

/* void ChatDatabase::my_database_DML_friend(string sender, string receiver, int mode)
{

    ostringstream buf;
    buf << "select id from friends where userid = '" << sender << "' or friendid = '" << receiver << "';";
    string statement = buf.str();

    MYSQL_RES *res = get_MYSQL_RES(mysql, statement.c_str());

    MYSQL_ROW row; // 按上面的sql语句搜索一定有两行，不存在的用户在搜索阶段就排除了
    row = mysql_fetch_row(res);
    string first = row[0];
    row = mysql_fetch_row(res);
    string second = row[0];

    buf.str("");
    statement.clear();
    if (mode == ADD)
        buf << "insert into user_friend(usr_id,friend_id) value (" << first << "," << second << ");";
    else if (mode == DEL)
        buf << "delete from user_friend where (usr_id = "
            << first << " and friend_id = " << second << ") or (usr_id = "
            << second << " and friend_id = " << first << ");";
    statement = buf.str();

    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        cout << "mysql_query error" << endl;
        return;
    }
}
 */